package com.example.mytestdemo.scale.zoom

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.PropertyValuesHolder
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import android.view.animation.DecelerateInterpolator
import android.widget.FrameLayout
import androidx.core.view.GestureDetectorCompat

/**
 * @Description:支持控件缩放，旋转, 双击放大缩小，绘制， 生成图片等
 * @Author: tgw
 * @CreateDate: 2022/4/22 10:46
 * 1.提到Android中的缩放，那肯定与scaleX，scaleY有关，通过这两个api可以方便的实现view的放大缩小
 * 但是这样的话会有问题我们可以想象一下假设手机是1080x1920，控件大小也是1080x1920， 这时刚好填充满手机屏幕，可是当放大一倍后
 * 就会出现问题，什么问题呢？假设原先控件上四个边角都有一个4x4的带颜色的小方块，当控件放大两倍后为2160x3840，这时手机屏幕中内容显示不全
 * 鉴于这种问题我们一般是让该控件可被用户拖拽查看，拖拽的话就要使用到translationX，与translationY
 *
 *  2.既然是平移那就涉及到了x与y方向能够平移多远距离的问题，有一个平移边界，这个边界就是我们缩放增加的大小，
 *  如果说缩放到2160x3840，x方向增大了1080，那么可以向左向右各平移最多540的距离，具体的移动可以在 onTouchEvent方法中进行计算设置，
 *  另外在进行缩放操作时如果发现控件的x，y进行过平移那么将translationX，与translationY置为0进行一个复位
 *
 *  3.到了这里缩放与平移已经完成，后面就是通过手势双指进行一个缩放操作，通过 event的MotionEvent.ACTION_POINTER_DOWN，检测双指事件
 *  然后通过三角函数得到两点之间的距离spacing1，缩放时候移动得到两指距离spacing2，得到缩放系数 spacing = spacing2/spacing1
 *  然后乘以现有的缩放比例：mScaleFactor = mScaleFactor * spacing,得到控件将要缩放的比例，在缩放过程中也要进行缩放边界的判断
 *
 *  4./现在关键就是旋转问题了，因为旋转后控件宽高相比于屏幕宽高变化，一些缩放系数与边界判断可以看doSetCWRotation方法，另外移动的时候也是要根据旋转角度进行判断的
 */
class HomeworkZoomView2 @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
    var TAG = "HomeworkZoomView"

    // 属性变量
    private var translationX // 移动X
            = 0f
    private var translationY // 移动Y
            = 0f
    private var mScaleFactor = 1f // 伸缩比例
    private var mRotation // 旋转角度
            = 0

    // 移动过程中临时变量
    private var actionX = 0f
    private var actionY = 0f
    private var spacing = 0f
    private var moveType // 0=未选择，1=correct_tool_drag，2=缩放
            = 0

    //动画正在执行中
    private var isDoing = false
    private val MAX_SCALE = 2.0f
    private val MIN_SCALE = 1.0f
    var mGestureDetector: GestureDetectorCompat? = null
    private var mLastTouchX = 0f
    private var mLastTouchY = 0f
    private var originWidth //控件的原始长度
            = 0
    private var originHeight //控件的原始宽度
            = 0
    private var originScale = 1f //缩放的回弹参数,作为缩放比例最小系数
    private val isOpenMultiFingered = false
    private fun init(context: Context) {
        mGestureDetector = GestureDetectorCompat(getContext(), CorrectGestureListener())
        //        service = ARouter.getInstance().navigation(MultiFingeredPaintService.class);
//        if(service != null){
//            isOpenMultiFingered = service.isOpenMultiFingered();
//        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        //获取控件的长宽
        originWidth = MeasureSpec.getSize(widthMeasureSpec)
        originHeight = MeasureSpec.getSize(heightMeasureSpec)
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        //getParent().requestDisallowInterceptTouchEvent(true);
//        if(ev.getAction() == MotionEvent.ACTION_MOVE){
//            if(mScaleFactor == 1){
//                return false;
//            }
//        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        return super.dispatchTouchEvent(ev)
    }

    interface OnSetTouchEventListener {
        fun setTouchEvent(event: MotionEvent?)
        fun cancel()
    }

    private var setTouchEventListener: OnSetTouchEventListener? = null
    fun setTouchEvent(setTouchEventListener: OnSetTouchEventListener?) {
        this.setTouchEventListener = setTouchEventListener
    }

    var notDo = false
    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        // Log.e("seesee", "onTouchEvent " + event.getActionMasked());
        if (isDoing) {
            return super.onTouchEvent(event)
        }
        if (isOpenMultiFingered) {
            if (event.pointerCount == 1) {
                if (setTouchEventListener != null) {
                    setTouchEventListener!!.setTouchEvent(event)
                    parent.requestDisallowInterceptTouchEvent(true)
                    return super.onTouchEvent(event)
                }
            }
            if (event.actionMasked == MotionEvent.ACTION_POINTER_DOWN) {
                if (setTouchEventListener != null) {
                    setTouchEventListener!!.cancel()
                }
            }
        }

        //注册双击事件
        if (mGestureDetector != null) {
            val a = mGestureDetector!!.onTouchEvent(event)
        }
        when (event.action and MotionEvent.ACTION_MASK) {
            MotionEvent.ACTION_DOWN -> {
                moveType = 1
                actionX = event.rawX
                actionY = event.rawY
            }
            MotionEvent.ACTION_POINTER_DOWN -> {
                moveType = 2
                spacing = getSpacing(event)
                mLastTouchX = event.rawX
                mLastTouchY = event.rawY
                Log.d(TAG, "onTouchEvent ACTION_POINTER_DOWN mLastTouchX: $mLastTouchX")
                Log.d(TAG, "onTouchEvent ACTION_POINTER_DOWN mLastTouchY: $mLastTouchY")
            }
            MotionEvent.ACTION_MOVE -> if (isOpenMultiFingered) {
                Log.d(TAG, "onTouchEvent isOpenMultiFingered mScaleFactor: $mScaleFactor")
                Log.d(TAG, "onTouchEvent isOpenMultiFingered spacing: $spacing")
                mScaleFactor = mScaleFactor * getSpacing(event) / spacing
                Log.d(TAG, "onTouchEvent isOpenMultiFingered mScaleFactor: $mScaleFactor")
                val canScale = checkScaleBound()
                if (canScale) {
                    //缩放过程中位置偏移
                    val disX = event.rawX - mLastTouchX
                    val disY = event.rawY - mLastTouchY
                    Log.d(TAG, "onTouchEvent isOpenMultiFingered translationX: $translationX")
                    Log.d(TAG, "onTouchEvent isOpenMultiFingered translationY: $translationY")
                    setTranslationXY(translationX + disX, translationY + disY)
                }
                mLastTouchX = event.rawX
                mLastTouchY = event.rawY
            } else {
                if (moveType == 1) {
                    var canMove = false
                    canMove = if (mRotation == 90 || mRotation == 270) {
                        checkRotationTranslation(event.rawX - actionX, event.rawY - actionY)
                    } else {
                        checkTranslation(event.rawX - actionX, event.rawY - actionY)
                    }
                    actionX = event.rawX
                    actionY = event.rawY
                    if (!canMove) {
                        zoomNotHandler = true
                        parent.requestDisallowInterceptTouchEvent(false)
                    } else {
                        zoomNotHandler = false
                    }
                } else if (moveType == 2) {
                    Log.d(TAG, "onTouchEvent moveType == 2 mScaleFactor: $mScaleFactor")
                    Log.d(TAG, "onTouchEvent moveType == 2 spacing: $spacing")
                    mScaleFactor = mScaleFactor * getSpacing(event) / spacing
                    Log.d(TAG, "onTouchEvent moveType == 2 mScaleFactor: $mScaleFactor")
                    val canScale = checkScaleBound()
                    if (canScale) {
                        //缩放过程中位置偏移
                        val disX = event.rawX - mLastTouchX
                        val disY = event.rawY - mLastTouchY
                        Log.d(TAG, "onTouchEvent moveType == 2 mLastTouchX: $mLastTouchX")
                        Log.d(TAG, "onTouchEvent moveType == 2 mLastTouchY: $mLastTouchY")
                        Log.d(TAG, "onTouchEvent moveType == 2 disX: $disX")
                        Log.d(TAG, "onTouchEvent moveType == 2 disY: $disY")
                        Log.d(TAG, "onTouchEvent moveType == 2 event.getRawX(): " + event.rawX)
                        Log.d(TAG, "onTouchEvent moveType == 2  event.getRawY(): " + event.rawY)
                        Log.d(TAG, "onTouchEvent moveType == 2  translationX: $translationX")
                        Log.d(TAG, "onTouchEvent moveType == 2  translationY: $translationY")
                        setTranslationXY(translationX + disX, translationY + disY)
                    }
                    mLastTouchX = event.rawX
                    mLastTouchY = event.rawY
                    Log.d(TAG, "onTouchEvent moveType == 2  endm LastTouchX: $mLastTouchX")
                    Log.d(TAG, "onTouchEvent moveType == 2  endm mLastTouchY: $mLastTouchY")
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
                upAnimator(moveType)
                moveType = 0
            }
        }
        return super.onTouchEvent(event)
    }

    private fun checkTranslation(disX: Float, disY: Float): Boolean {
        //判断左右滑，还是上下滑

        //如果绘制区域在可视范围内，则不能滑动x，y坐标
        val width = originWidth
        val height = originHeight
        val tempWidth = width * mScaleFactor
        val tempHeight = height * mScaleFactor
        //        if(mRotation == 90 || mRotation == 270){
//            tempWidth = height*mScaleFactor;
//            tempHeight = width*mScaleFactor;
//        }
        Log.d(TAG, "checkTranslation width: $width")
        Log.d(TAG, "checkTranslation height: $height")
        Log.d(TAG, "checkTranslation mScaleFactor: $mScaleFactor")
        Log.d(TAG, "checkTranslation tempWidth: $tempWidth")
        Log.d(TAG, "checkTranslation tempHeight: $tempHeight")
        val canMove = true
        if (tempWidth <= width && tempHeight <= height) {
            return false
        }
        var resultX = translationX + disX
        var resultY = translationY + disY
        Log.d(TAG, "checkTranslation disX: $disX")
        Log.d(TAG, "checkTranslation disY: $disY")
        Log.d(TAG, "checkTranslation translationX: $translationX")
        Log.d(TAG, "checkTranslation translationY: $translationY")
        Log.d(TAG, "checkTranslation resultX: $resultX")
        Log.d(TAG, "checkTranslation resultY: $resultY")
        if (tempWidth <= width) {
            resultX = translationX //不动
        } else {
            val maxWDis = (tempWidth - width) / 2
            if (resultX <= -maxWDis) {
                resultX = -maxWDis
                //                canMove = false;
            } else if (resultX >= maxWDis) {
                resultX = maxWDis
                //                canMove = false;
            } else {
                parent.requestDisallowInterceptTouchEvent(true)
            }
        }
        if (tempHeight <= height) {
            resultY = translationY
        } else {
            val maxHDis = (tempHeight - height) / 2
            if (resultY <= -maxHDis) {
                resultY = -maxHDis
                //                canMove = false;
            } else if (resultY >= maxHDis) {
                resultY = maxHDis
                //                canMove = false;
            } else {
                parent.requestDisallowInterceptTouchEvent(true)
            }
        }
        if (canMove) {
            //doUp = false;
            setTranslationXY(resultX, resultY)
        }
        return canMove
    }

    private fun checkRotationTranslation(disX: Float, disY: Float): Boolean {
        //判断左右滑，还是上下滑

        //如果绘制区域在可视范围内，则不能滑动x，y坐标
        val width = originWidth
        val height = originHeight
        val tempWidth = height * mScaleFactor
        val tempHeight = width * mScaleFactor
        //        if(mRotation == 90 || mRotation == 270){
//            tempWidth = height*mScaleFactor;
//            tempHeight = width*mScaleFactor;
//        }
        Log.d(TAG, "checkTranslation width: $width")
        Log.d(TAG, "checkTranslation height: $height")
        Log.d(TAG, "checkTranslation mScaleFactor: $mScaleFactor")
        Log.d(TAG, "checkTranslation tempWidth: $tempWidth")
        Log.d(TAG, "checkTranslation tempHeight: $tempHeight")
        var canMove = true
        if (tempWidth <= width && tempHeight <= height) {
            return false
        }
        var resultX = translationX + disX
        var resultY = translationY + disY
        Log.d(TAG, "checkTranslation disX: $disX")
        Log.d(TAG, "checkTranslation disY: $disY")
        Log.d(TAG, "checkTranslation translationX: $translationX")
        Log.d(TAG, "checkTranslation translationY: $translationY")
        Log.d(TAG, "checkTranslation resultX: $resultX")
        Log.d(TAG, "checkTranslation resultY: $resultY")
        if (tempWidth <= width) {
            resultX = translationX //不动
        } else {
            val maxWDis = (tempWidth - width) / 2
            if (resultX <= -maxWDis) {
                resultX = -maxWDis
                canMove = false
            } else if (resultX >= maxWDis) {
                resultX = maxWDis
                canMove = false
            } else {
                parent.requestDisallowInterceptTouchEvent(true)
            }
        }
        if (tempHeight <= height) {
            resultY = translationY
        } else {
            val maxHDis = (tempHeight - height) / 2
            if (resultY <= -maxHDis) {
                resultY = -maxHDis
                canMove = false
            } else if (resultY >= maxHDis) {
                resultY = maxHDis
                canMove = false
            } else {
                parent.requestDisallowInterceptTouchEvent(true)
            }
        }
        if (canMove) {
            //doUp = false;
            setTranslationXY(resultX, resultY)
        }
        return canMove
    }

    private fun upAnimator(moveType: Int) {
        if (isDoing || moveType != 2) return  //双击事件缩放中返回
        val width = originWidth
        val height = originHeight
        var tempWidth = width * mScaleFactor
        var tempHeight = height * mScaleFactor
        if (mRotation == 90 || mRotation == 270) {
            tempWidth = height * mScaleFactor
            tempHeight = width * mScaleFactor
        }

        //没有变化则不需要判断
        if (translationX == 0f && translationY == 0f && mScaleFactor == originScale) {
            return
        }
        val resultX: Float
        val resultY: Float
        if (mRotation == 90 || mRotation == 270) {
            resultX = (1 - mScaleFactor) * originHeight + Math.abs(translationX)
            resultY = (1 - mScaleFactor) * originWidth + Math.abs(translationY)
            Log.d(TAG, "upAnimator mScaleFactor: $mScaleFactor")
            Log.d(TAG, "upAnimator tempHeight: $tempHeight")
            Log.d(TAG, "upAnimator tempWidth: $tempWidth")
            Log.d(TAG, "upAnimator width: $width")
            Log.d(TAG, "upAnimator height: $height")
            Log.d(
                TAG,
                "upAnimator (1 - mScaleFactor) * originHeight: " + (1 - mScaleFactor) * originHeight
            )
            Log.d(
                TAG,
                "upAnimator (1 - mScaleFactor) * originWidth: " + (1 - mScaleFactor) * originWidth
            )
            Log.d(
                TAG,
                "upAnimator ((1 - mScaleFactor) * originHeight - width) / 2: " + ((1 - mScaleFactor) * originHeight - width) / 2
            )
            Log.d(
                TAG,
                "upAnimator ((1 - mScaleFactor) * originWidth - height) / 2: " + ((1 - mScaleFactor) * originWidth - height) / 2
            )
            Log.d(TAG, "upAnimator translationX: $translationX")
            Log.d(TAG, "upAnimator translationY: $translationY")
            Log.d(TAG, "upAnimator resultX: $resultX")
            Log.d(TAG, "upAnimator resultY: $resultY")
            val isNeedBack = isRotationNeedBack(
                mScaleFactor,
                resultX,
                resultY,
                originWidth.toFloat(),
                originHeight.toFloat()
            )
            //根据观察，向下滑translationY大于0，向上滑translationY小于0
            //在缩放系数小于1的时候，resultY永远大于0，当缩小时，缩小的距离加上 移动距离的绝对值小于当前的布局的一半时
//            if(mScaleFactor <1 && resultY > (float) originWidth/2){
//                isNeedBack = true;
//            }else if(mScaleFactor >1&&resultY>0){  //在缩放系数>于1的时候，resultY永远大于0，当缩小时，缩小的距离加上 移动距离的绝对值小于当前的布局的一半时
//                isNeedBack = true;
//            }
//
//            if(mScaleFactor <1 && resultX > (float) originHeight/2){
//                isNeedBack = true;
//            }else if(mScaleFactor >1&&resultX>0){
//                isNeedBack = true;
//            }
            if (isNeedBack) {
                zoomAnimator(mScaleFactor, originScale, 0f, 0f)
                return
            }
            //            if (mScaleFactor < originScale) {
//                mScaleFactor = MIN_SCALE;
//                zoomAnimator(mScaleFactor, originScale, 0, 0);
//            } else if (mScaleFactor > MAX_SCALE) {
//                mScaleFactor = MAX_SCALE;
//                zoomAnimator(mScaleFactor, originScale, 0, 0);
//            }
        } else {
//            resultX = (1 - mScaleFactor) * originWidth / 2 + translationX;
//            resultY = (1 - mScaleFactor) * originHeight / 2 + translationY;
//            boolean isNeedBack = isNeedBack(resultX, resultY, tempWidth, tempHeight);
//
//            if (isNeedBack) {
//                zoomAnimator(mScaleFactor, originScale, 0, 0);
//            }
            resultX = (1 - mScaleFactor) * originWidth + Math.abs(translationX)
            resultY = (1 - mScaleFactor) * originHeight + Math.abs(translationY)
            val isNeedBack = isRotationNeedBack(
                mScaleFactor,
                resultX,
                resultY,
                originHeight.toFloat(),
                originWidth.toFloat()
            )
            if (isNeedBack) {
                zoomAnimator(mScaleFactor, originScale, 0f, 0f)
                return
            }
            //            if (mScaleFactor < MIN_SCALE) {
//                mScaleFactor = MIN_SCALE;
//                zoomAnimator(mScaleFactor, originScale, 0, 0);
//            } else if (mScaleFactor > MAX_SCALE) {
//                mScaleFactor = MAX_SCALE;
//                zoomAnimator(mScaleFactor, originScale, 0, 0);
//            }
        }
    }

    private fun isNeedBack(
        resultX: Float,
        resultY: Float,
        tempWidth: Float,
        tempHeight: Float
    ): Boolean {
        if (resultX > 0) {
            return true
        } else if (resultX + tempWidth < originWidth) {
            return true
        }
        if (resultY > 0) {
            return true
        } else if (resultY + tempHeight < originHeight) {
            return true
        }
        return false
    }

    private fun isRotationNeedBack(
        scaleFactor: Float,
        resultX: Float,
        resultY: Float,
        originHeight: Float,
        originWidth: Float
    ): Boolean {
        //根据观察，向下滑translationY大于0，向上滑translationY小于0
        //在缩放系数小于1的时候，resultY永远大于0，当缩小时，缩小的距离加上 移动距离的绝对值，小于当前的布局的一半时，
        // 认为你应该要恢复原状了，防止缩小时 偏移到到看不见了

        //在缩放系数大于1的时候，((1 - mScaleFactor) * originWidth)的值，假设mScaleFactor为最大的2倍时，
        // 当未移动时resultY=-originWidth，当移动后就会translationX就会产生偏移量（上面取得绝对值：即偏移量）
        //当缩小时，((1 - mScaleFactor) * originWidth)的值会变小，当缩放的大小+偏移量>0时
        // 认为整体应该要恢复原状了，防止缩小时 偏移到到看不见了
        var isNeedBack = false
        if (scaleFactor < 1 && resultY > originHeight / 2) { //当90°时原始宽高颠倒
            isNeedBack = true
        } else if (scaleFactor > 1 && resultY > 0) {
            //在缩放系数>于1的时候，resultY永远大于0，当缩小时，
            // 缩小的距离加上 移动距离的绝对值小于当前的布局的一半时
            isNeedBack = true
        }
        if (scaleFactor < 1 && resultX > originWidth / 2) {
            isNeedBack = true
        } else if (scaleFactor > 1 && resultX > 0) {
            isNeedBack = true
        }
        return isNeedBack
    }

    private fun setTranslationXY(transX: Float, transY: Float) {
        translationX = transX
        translationY = transY
        Log.d(TAG, "setTranslationXY translationX: $translationX")
        Log.d(TAG, "setTranslationXY translationY: $translationY")
        //Log.e("xxyy", "translationX="+translationX+" || translationY="+translationY);
        setTranslationX(translationX)
        setTranslationY(translationY)
    }

    /**
     * 缩放边界值判断
     *
     * @return 判断达到边界值停止后续操作
     */
    private fun checkScaleBound(): Boolean {
        val canScale: Boolean
        Log.d(TAG, "checkScaleBound--mScaleFactor: $mScaleFactor")
        Log.d(TAG, "checkScaleBound--mScaleFactor--: " + mScaleFactor / originScale)
        if (getTranslationX() != 0f || getTranslationY() != 0f) {
            setTranslationXY(0f, 0f)
        }
        if (mScaleFactor < originScale) {
            canScale = false
            mScaleFactor = originScale
        } else if (mScaleFactor > 2 * originScale) {
            canScale = false
            mScaleFactor = 2 * originScale
        } else {
            canScale = true
            parent.requestDisallowInterceptTouchEvent(true)
        }
        scaleX = mScaleFactor
        scaleY = mScaleFactor
        return canScale
    }

    fun doSetRotation(rotation: Int) {
        mRotation = rotation
        var tempScale = 1f
        setTranslationX(0.also { translationX = it.toFloat() }.toFloat())
        setTranslationY(0.also { translationY = it.toFloat() }.toFloat())
        if (mRotation == 0) {
            originScale = 1f
            tempScale = 1f
        } else if (mRotation == 90) {
            originScale = this.height.toFloat() / this.width
            tempScale = originScale
        } else if (mRotation == 180) {
            originScale = 1f
            tempScale = 1f
        } else if (mRotation == 270) {
            originScale = this.height.toFloat() / this.width
            tempScale = originScale
        }
        mScaleFactor = mScaleFactor * tempScale
        checkScaleBound()
        this.rotation = mRotation.toFloat()
    }

    /**
     * 对外方法，动态旋转，规定四个角度,顺时针
     */
    fun doSetCWRotation() {
        var tempScale = 1f
        setTranslationX(0.also { translationX = it.toFloat() }.toFloat())
        setTranslationY(0.also { translationY = it.toFloat() }.toFloat())
        if (mRotation == 0) {
            originScale = this.height.toFloat() / this.width
            tempScale = originScale
            mRotation = 90
        } else if (mRotation == 90) {
            originScale = 1f
            tempScale = this.width.toFloat() / this.height
            mRotation = 180
        } else if (mRotation == 180) {
            originScale = this.height.toFloat() / this.width
            tempScale = originScale
            mRotation = 270
        } else if (mRotation == 270) {
            originScale = 1f
            tempScale = this.width.toFloat() / this.height
            mRotation = 0
        }

//        Log.d(TAG, "doSetRotation mRotation: "+mRotation);
//        Log.d(TAG, "doSetRotation originScale: "+originScale);
//        Log.d(TAG, "doSetRotation tempScale: "+tempScale);
//        Log.d(TAG, "doSetRotation translationX: "+translationX);
//        Log.d(TAG, "doSetRotation translationY: "+translationY);
//        Log.d(TAG, "doSetRotation getWidth(): "+getWidth());
//        Log.d(TAG, "doSetRotation getHeight(): "+getHeight());
        mScaleFactor = mScaleFactor * tempScale
        checkScaleBound()
        this.rotation = mRotation.toFloat()
        if (setRotationListener != null) {
            setRotationListener!!.setRotation(position, mRotation)
        }
    }

    /**
     * 按照比例系数进行xy的缩放
     */
    fun doSetScaleXY(multiple: Float) {
        mScaleFactor = originScale * multiple
        checkScaleBound()
    }

    /**
     * 对外方法，动态旋转，规定四个角度，逆时针
     */
    fun doSetCCWRotation() {
        var tempScale = 1f
        setTranslationX(0.also { translationX = it.toFloat() }.toFloat())
        setTranslationY(0.also { translationY = it.toFloat() }.toFloat())
        if (mRotation == 0) {
            originScale = this.height.toFloat() / this.width
            tempScale = originScale
            mRotation = 270
        } else if (mRotation == 90) {
            originScale = 1f
            tempScale = this.width.toFloat() / this.height
            mRotation = 0
        } else if (mRotation == 180) {
            originScale = this.height.toFloat() / this.width
            tempScale = originScale
            mRotation = 90
        } else if (mRotation == 270) {
            originScale = 1f
            tempScale = this.width.toFloat() / this.height
            mRotation = 180
        }

//        Log.d(TAG, "doSetRotation mRotation: "+mRotation);
//        Log.d(TAG, "doSetRotation originScale: "+originScale);
//        Log.d(TAG, "doSetRotation tempScale: "+tempScale);
//        Log.d(TAG, "doSetRotation translationX: "+translationX);
//        Log.d(TAG, "doSetRotation translationY: "+translationY);
//        Log.d(TAG, "doSetRotation getWidth(): "+getWidth());
//        Log.d(TAG, "doSetRotation getHeight(): "+getHeight());
        mScaleFactor = mScaleFactor * tempScale
        checkScaleBound()
        this.rotation = mRotation.toFloat()
        if (setRotationListener != null) {
            setRotationListener!!.setRotation(position, mRotation)
        }
    }

    // 触碰两点间距离
    private fun getSpacing(event: MotionEvent): Float {
        //通过三角函数得到两点间的距离
        val x = event.getX(0) - event.getX(1)
        val y = event.getY(0) - event.getY(1)
        return Math.sqrt((x * x + y * y).toDouble()).toFloat()
    }

    val bitmap: Bitmap?
        get() {
            val width = this.width
            val height = this.height
            if (height <= 0 || width <= 0) {
                return null
            }
            val mScreenshot = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444)
            val c = Canvas(mScreenshot)
            c.drawFilter = PaintFlagsDrawFilter(
                0,
                Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG
            )
            draw(c)
            return mScreenshot
        }

    fun getmRotation(): Int {
        return mRotation
    }

    fun setAddScale(add: Float) {
//        BigDecimal b1 = new BigDecimal(Float.toString(mScaleFactor));
//        BigDecimal b2 = new BigDecimal(Float.toString(add));
//        float addScale = b1.add(b2).floatValue();
//
//
//        if (addScale > MAX_SCALE) {
//            return;
//        }
        mScaleFactor = mScaleFactor + add * originScale
        checkScaleBound()
        upAnimator(2)
    }

    fun setReduceScale(reduce: Float) {
//        BigDecimal b1 = new BigDecimal(Float.toString(mScaleFactor));
//        BigDecimal b2 = new BigDecimal(Float.toString(reduce));
//        float reduceScale = b1.subtract(b2).floatValue();
//        if (reduceScale < MIN_SCALE) {
//            return;
//        }
        mScaleFactor = mScaleFactor - reduce * originScale
        checkScaleBound()
        upAnimator(2)
    }

    fun adjustPhotoRotation(): Bitmap? {
        val bm = bitmap ?: return null
        val m = Matrix()
        m.setRotate(mRotation.toFloat(), bm.width.toFloat() / 2, bm.height.toFloat() / 2)
        try {
            return Bitmap.createBitmap(bm, 0, 0, bm.width, bm.height, m, true)
        } catch (ex: OutOfMemoryError) {
        }
        return null
    }

    /**
     * 双击手势操作
     */
    private inner class CorrectGestureListener : SimpleOnGestureListener() {
        override fun onDoubleTap(e: MotionEvent): Boolean {
            if (isDoing) return super.onDoubleTap(e)
            isDoing = true
            val endFactor: Float
            val scaleCenterX: Float
            val scaleCenterY: Float
            if (mScaleFactor == originScale || mScaleFactor == 1f) {
                scaleCenterX = 0f
                scaleCenterY = 0f
                endFactor = originScale * 2
            } else {
                scaleCenterX = 0f
                scaleCenterY = 0f
                endFactor = originScale
            }
            zoomAnimator(mScaleFactor, endFactor, scaleCenterX, scaleCenterY)
            return super.onDoubleTap(e)
        }
    }

    private fun zoomAnimator(
        startVal: Float,
        endVal: Float,
        scaleCenterX: Float,
        scaleCenterY: Float
    ) {
        if (mScaleAnimator == null) {
            newZoomAnimation()
        }
        if (mScaleAnimator!!.isRunning) {
            return
        }
        val startTranX = translationX
        val startTranY = translationY
        val scaleHolder = PropertyValuesHolder
            .ofFloat(PROPERTY_SCALE, startVal, endVal)
        val tranXHolder = PropertyValuesHolder
            .ofFloat(PROPERTY_TRANX, startTranX, scaleCenterX)
        val tranYHolder = PropertyValuesHolder
            .ofFloat(PROPERTY_TRANY, startTranY, scaleCenterY)
        mScaleAnimator!!.setValues(scaleHolder, tranXHolder, tranYHolder)
        mScaleAnimator!!.duration = DEFAULT_SCALE_DURATION.toLong()
        mScaleAnimator!!.start()
    }

    var mScaleAnimator: ValueAnimator? = null

    /**
     * 缩放动画
     */
    private fun newZoomAnimation() {
        mScaleAnimator = ValueAnimator()
        mScaleAnimator!!.interpolator = DecelerateInterpolator()
        mScaleAnimator!!.addUpdateListener { animation -> //update scaleFactor & tranX & tranY
            val scaleValue = animation.getAnimatedValue(PROPERTY_SCALE) as Float
            val tranXValue = animation.getAnimatedValue(PROPERTY_TRANX) as Float
            val tranYValue = animation.getAnimatedValue(PROPERTY_TRANY) as Float
            //                if (scaleValue<originScale){
//                    mScaleFactor = MIN_SCALE;
//                }else {
            mScaleFactor = scaleValue
            //                }
            scaleX = scaleValue
            scaleY = scaleValue
            setTranslationXY(tranXValue, tranYValue)
        }
        mScaleAnimator!!.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationStart(animation: Animator) {}
            override fun onAnimationEnd(animation: Animator) {
                isDoing = false
            }

            override fun onAnimationCancel(animation: Animator) {}
        })
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        if (mScaleAnimator != null && mScaleAnimator!!.isRunning) {
            mScaleAnimator!!.cancel()
        }
    }

    interface SetRotationListener {
        fun setRotation(position: Int, rotation: Int)
    }

    private var setRotationListener: SetRotationListener? = null
    fun setSetRotationListener(listener: SetRotationListener?) {
        setRotationListener = listener
    }

    private var position = 0
    fun setPosition(position: Int) {
        this.position = position
    }

    private var tempName //生成需要上传的本地路径,上传成功删除
            : String? = null

    fun setTempName(tempName: String?) {
        this.tempName = tempName
    }

    /**
     * 自己是否不处理
     * true 不处理
     * false 自己处理
     */
    var zoomNotHandler: Boolean? = null
        private set

    init {
        isClickable = true
        init(context)
    }

    companion object {
        private const val DEFAULT_SCALE_DURATION = 300
        private const val PROPERTY_SCALE = "scale"
        private const val PROPERTY_TRANX = "tranX"
        private const val PROPERTY_TRANY = "tranY"
    }
}